#include <iostream>
#include <typeinfo>
using namespace std;
#define VIRTUAL
#define STATIC
#define PRIMARY

class Base {
public:
  Base(int i): baseI(i) {}

  STATIC static void countI() {
    cout << "Call Base::countI() static" << endl;
  }


  VIRTUAL virtual void print(void){
    cout << "Call Base::print()" << endl;
  }

  VIRTUAL virtual void print2(void){
    cout << "Call Base::print2()" << endl;
  }

  VIRTUAL virtual ~Base() {
    cout << "Call Base::~Base()" << endl;
  }


  // DEPRECATED
  PRIMARY int getI() { 
    return baseI;
  }
private:
  int baseI;
  static int baseS;
};


// pFn 是一个指针，指针指向一个函数
typedef void (*pFn)();
// pArr 是一个数组，其元素为指针，其指向一个指针，这个指针指向一个函数
typedef pFn *pArr[];
// VFPTR 指向指针数组的指针
typedef pArr *VFPTR;

void testBase(Base &base) {

  // 获取 vptr，其指向虚函数表
  VFPTR vptr = (VFPTR)&base;
  // 获取 虚函数表首元素地址
  // 第一个虚函数调用
  (*(*vptr))[0](); 
  (*((*(*vptr)) + 0))();
  // 第二个虚函数调用
  (*(*vptr))[1](); 
  (*((*(*vptr)) + 1))();

  cout << "对象的内存地址：" << &base << endl;
  cout << "Base* type_info 地址为：" <<  &typeid(&base) << endl;
  cout << "Base* type_info 信息.name(): " << typeid(&base).name() << endl;
  cout << "Base type_info 地址为：" <<  &typeid(base) << endl;
  cout << "Base type_info 信息.name(): " << typeid(base).name() << endl;

  cout << "虚函数表地址 vtbl: " << *(*vptr) << endl;
  long vtbl_addr = (long)**vptr;
  printf("虚函数表上一个元素的地址: %p\n", (void*)(vtbl_addr - 8));
  printf("虚函数表上一个元素所指向的地址: %p\n", *(long**)(vtbl_addr - 8));
  
  printf("虚函数表，第一个元素的地址: %p\n", (void*)vtbl_addr);
  printf("虚函数表，第二个元素的地址: %p\n", (void*)(vtbl_addr + 8));


  cout << "获取虚函数表首地址的值" << *(*vptr) << endl;
  cout << "type_info 的地址：" << ((*(*vptr)) - 1) << endl;
  cout << "第一个虚函数的地址：" << ((*(*vptr)) + 0) << endl;
  cout << "第二个虚函数的地址：" << ((*(*vptr)) + 1) << endl;
  cout << "第二个虚函数的地址：" << ((*(*vptr)) + 2) << endl;


  cout << "通过指针获取数据成员 baseI: " <<  *(int *)((void **)vptr + 1) << endl;
}


int main() {
  Base b(100);
  Base b2(200);
  testBase(b);
  testBase(b2);
  return 0;
}
